#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#include "http.h"

static void * http_dispatch(void *arg);

int http_bind_socket(in_addr_t ip, int port) 
{

   int r,  nfd, flags, on = 1;
   struct sockaddr_in addr;
   
   nfd = socket(AF_INET, SOCK_STREAM, 0);
   if (nfd < 0) return -1;
  
   /* set socket nonblocking */
   if ((flags = fcntl(nfd, F_GETFL, NULL)) < 0 ||
       fcntl(nfd, F_SETFL, flags | O_NONBLOCK) == -1)
     return -1;
   /* set socket closeonexec */
#ifdef _EVENT_HAVE_SETFD
   if ((flags = fcntl(nfd, F_GETFD, NULL)) < 0 ||
       fcntl(nfd, F_SETFD, flags | FD_CLOEXEC) == -1)
     return -1;
#endif
  
   setsockopt(nfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on));
   setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on));
   memset(&addr, 0, sizeof(addr));
   addr.sin_family      = AF_INET;
   addr.sin_addr.s_addr = ip;
   addr.sin_port        = htons(port);
    
   r = bind(nfd, (struct sockaddr*)&addr, sizeof(addr));
   if (r < 0) return -1;
   r = listen(nfd, 128);
   if (r < 0) return -1;
  
   return nfd;
}
  
int http_run(scws_t s, int nfd, int timeout_secs, int nthreads,
                     void (*cb)(struct evhttp_request *, void *)) 
{
   int r, i = 0;
   struct event_base *base;
   struct evhttp * httpd;
   req_arg *arg;

   pthread_t ths[nthreads];
   evthread_use_pthreads();
   for (i = 0; i < nthreads; i++) {
     base = event_init();
     if (base == NULL) return -1;
     httpd = evhttp_new(base);
     if (httpd == NULL) return -1;
     r = evhttp_accept_socket(httpd, nfd);
     if (r != 0) return -1;
     // TODO
     // evhttp_set_cb(http, "/dump", dump_request_cb, NULL);
     arg = (req_arg *)malloc(sizeof(req_arg));
     if (NULL == arg)
 	return -1;
     arg->buf = (char *)malloc(32768);
     if (NULL == arg->buf)
         return -1;
     arg->uri = (char *)malloc(32769);
     if (NULL == arg->uri)
	 return -1;
     arg->buf_len = 0;
     arg->uri_len = 0;
     arg->s = scws_fork(s);
     evhttp_set_gencb(httpd, cb, arg);
     evhttp_set_timeout(httpd, timeout_secs);
      
     r = pthread_create(&ths[i], NULL,  http_dispatch, base);
     if (r != 0) return -1;
   }
   for (i = 0; i < nthreads; i++) {
     pthread_join(ths[i], NULL);
   }
   return 0;
}
  
void * http_dispatch(void *arg) {
   event_base_dispatch((struct event_base*)arg);
   return NULL;
}
  
/*url地址解码*/
char *urldecode(const char *in, int len, char *out, int *urilen)
{
    char   temp[4];
    const char  *p, *pend;
	char *q;
    int             value;

	
    p = in, q = out;
	pend = p + len;

    while (p < pend) {
        if (*p == '+') {
            *q++ = ' ';
        } else if (*p == '%') {
            temp[0] = *(p + 1);
            temp[1] = *(p + 2);
            temp[2] = 0;
            sscanf(temp, "%x", &value);

            *q++ = 0xff & value;

            p += 2;
        } else {
            *q++ = *p;
        }

        p++;
    }
    *q = '\0';
	*urilen = q - out;
    return (char *) out;
}
